package remato.domain.server.ejb;


import static javax.persistence.CascadeType.ALL;
import static javax.persistence.CascadeType.MERGE;
import static javax.persistence.CascadeType.PERSIST;
import static javax.persistence.GenerationType.AUTO;
import static javax.persistence.TemporalType.TIMESTAMP;

import java.util.Date;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.Transient;
import javax.persistence.Version;

import remato.domain.common.Category;
import remato.domain.common.PropertyValue;
import remato.domain.common.Requirement;
import remato.domain.common.Stakeholder;
import remato.domain.common.impl.RequirementImpl;
/**
 * @author petterei, oranvik
 * @version $Id: RequirementEjb.java,v 1.4 2006-02-06 09:22:24 petterei Exp $
 */
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class RequirementEjb extends RequirementImpl implements Requirement {

	private Stakeholder persistableReporterOrOwner = null;
	private Stakeholder persistableAssignedTo = null;
	
	@Override
	@Id
	@GeneratedValue(strategy=AUTO)
	public Long getDbId() {
		return super.getDbId();
	}

	@Override
	@Lob
	public String getDescription() {
		return super.getDescription();
	}

	@Override
	public String getName() {
		return super.getName();
	}

	@Override
	@ManyToOne(targetEntity = CategoryEjb.class)
	public Category getCategory() {
		return super.getCategory();
	}

	
	@Override
	@Transient
	public Stakeholder getAssignedTo() {
		return getPersistableAssignedTo();
	}

	@Override
	public void setAssignedTo(Stakeholder newAssignedTo) {
		setPersistableAssignedTo(newAssignedTo);
	}

	/*
	 * For Hibernate or other ORM which need plain getters and setter without 
	 * magic logic.
	 */
	@ManyToOne(targetEntity = StakeholderEjb.class)
	public Stakeholder getPersistableAssignedTo() {
		return persistableAssignedTo;
	}

	/*
	 * For Hibernate or other ORM which need plain getters and setter without 
	 * magic logic.
	 */
	public void setPersistableAssignedTo(Stakeholder persistableAssignedTo) {
		this.persistableAssignedTo = persistableAssignedTo;
	}


	@Override
	@Transient
	public Stakeholder getReporterOrOwner() {
		return getPersistableReporterOrOwner();
	}

	@Override
	public void setReporterOrOwner(Stakeholder newReporterOrOwner) {
		setPersistableReporterOrOwner(newReporterOrOwner);
	}

	/*
	 * For Hibernate or other ORM which need plain getters and setter without 
	 * magic logic.
	 */
	@ManyToOne(targetEntity = StakeholderEjb.class)
	public Stakeholder getPersistableReporterOrOwner() {
		return persistableReporterOrOwner;
	}

	/*
	 * For Hibernate or other ORM which need plain getters and setter without 
	 * magic logic.
	 */
	public void setPersistableReporterOrOwner(Stakeholder persistableReporterOrOwner) {
		this.persistableReporterOrOwner = persistableReporterOrOwner;
	}


	@Override
	@ManyToMany(targetEntity = StakeholderEjb.class, cascade = { ALL })
	@JoinTable(name = "requirement_stakeholder",
			joinColumns = { @JoinColumn(name = "requirement_id") },
			inverseJoinColumns = { @JoinColumn(name = "stakeholder_id") })
	public Set<Stakeholder> getStakeholders() {
		return super.getStakeholders();
	}

	@Override
	@OneToMany(targetEntity = PropertyValueEjb.class, cascade = { ALL })
	@JoinColumn(name="requirement")
//	@Cascade(DELETE_ORPHAN) // can lead to database inconsistensy, should be used with care..
	public Set<PropertyValue> getPropertyValues() {
		return super.getPropertyValues();
	}

	@Override
	@ManyToMany(targetEntity = RequirementEjb.class, cascade = { ALL })
	@JoinTable(name = "requirement_to_requirement",
			joinColumns = { @JoinColumn(name = "requirement_id") },
			inverseJoinColumns = { @JoinColumn(name = "inverse_requirement_id") })
	public Set<Requirement> getLinkedToRequirements() {
		return super.getLinkedToRequirements();
	}

	@Override
//	@Column(unique = true, updatable = false) // could lead to resolvable database state..
	public Long getBusinessId() {
		return super.getBusinessId();
	}

	@Override
    @Temporal(TIMESTAMP)
    public Date getLastUpdatedDate() {
		return super.getLastUpdatedDate();
	}

	@Override
	public Integer getPriority() {
		return super.getPriority();
	}

	@Override
	public Integer getStatus() {
		return super.getStatus();
	}

	@Override
    @Temporal(TIMESTAMP)
	public Date getSubmittedDate() {
		return super.getSubmittedDate();
	}

	@Override
	@Transient
	public String getVersion() {
		return String.valueOf(getIntVersion());
	}

	// temporary version
	@Version  // see UserVersionType, applies also for businessID
	public int getIntVersion() {
		int version = 0;
		try { version = Integer.parseInt(super.getVersion()); } catch (Throwable e) {}
		return version;
	}

	public void setIntVersion(int version) {
		super.setVersion(String.valueOf(version));
	}
	
	/**
	 * Needed to trigger CGLib proxy (ie. if other CGLib-proxies is used as 
	 * parameter.)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		return super.equals(obj);
	}

}
